#!/usr/bin/env python
# -*- coding: utf-8 -*-

import unittest
import tatolib.sqlite3db as sqlite3db
import tatolib.taskobj as taskobj
import tatolib.strutil as strutil
import tatolib.timeutil as timeutil
import tatolib.errors   as errors

class TestCreateDB(unittest.TestCase):

    def create_objs(self):
        jing = taskobj.Task(name = strutil.u_("SayLoveToJing"),
                            detail = strutil.u_(""),
                            due = timeutil.utcdatetime(2011, 2, 3),
                            flags = {strutil.u_('mygirl'):   (1, False),
                                     strutil.u_('myfamily'): (10, False)})
        family = taskobj.Tag(name = strutil.u_("Family"),
                             detail = strutil.u_(""),
                             weighting = 4)
        work   = taskobj.Tag(name = strutil.u_("Work"),
                             detail = strutil.u_(""),
                             weighting = 2)
        return jing, family, work
    def test_create_db(self):
        db = sqlite3db.Database(":memory:")
        db.close()

    def test_assign_tag(self):
        db = sqlite3db.Database(":memory:")
        try:
            jing, family, work = self.create_objs()

            jing_id   = db.new(jing)
            family_id = db.new(family)
            work_id   = db.new(work)

            list_info = db.list(taskobj.Task)

            id1 = db.assigntag(jing_id, family_id)
            # Assign twice results in no-op
            id2 = db.assigntag(jing_id, family_id)
            self.assertTrue(id1 == family_id)
            self.assertTrue(id2 == family_id)

            list_info_assigned = db.list(taskobj.Task)

            self.assertTrue(len(list_info) == 1)
            self.assertTrue(len(list_info_assigned) == 1)

            jing_weighting1 = list_info[0][2]
            jing_weighting2 = list_info_assigned[0][2]
            self.assertTrue(jing_weighting1 < jing_weighting2)
        finally:
            db.close()
    def test_add_id_increase(self):
        db = sqlite3db.Database(":memory:")
        try:
            jing, family, work = self.create_objs()
            id = db.new(jing)
            self.assertTrue(id == 1)
            id2 = db.new(jing)
            self.assertTrue(id2 == 2)

            id_tag = db.new(family)
            try:
                id_tag2 = db.new(family)
                self.assertTrue(False)
            except errors.TaskObjectError:
                pass
            self.assertTrue(id_tag == 1)
            family.name = strutil.u_("Family2")
            id_tag2 = db.new(family)
            self.assertTrue(id_tag2 == 2)
        finally:
            db.close()
    def test_delete_obj(self):
        db = sqlite3db.Database(":memory:")
        try:
            jing, family, work = self.create_objs()
            task_id = db.new(jing)
            tag_id = db.new(family)

            db.delete(taskobj.Task, task_id)
            db.delete(taskobj.Tag, tag_id)

            found_task = db.getbyid(taskobj.Task, task_id)
            found_tag = db.getbyid(taskobj.Tag, tag_id)
            self.assertTrue(found_task is None)
            self.assertTrue(found_tag is None)
        finally:
            db.close()
    def test_update_obj(self):
        db = sqlite3db.Database(":memory:")
        try:
            jing, family, work = self.create_objs()

            task_id = db.new(jing)
            tag_id = db.new(family)
            db.new(work)

            original_flags = jing.flags
            jing.name   = strutil.u_("Can I say love to you?")
            jing.detail = jing.name
            jing.due    = timeutil.utcdatetime(2011,2,3)
            jing.complete = jing.due
            jing.setflag('mygirl')
            self.assertTrue(jing.flags['mygirl'][1])
            jing.setflag('mygirl', False)
            self.assertTrue(not jing.flags['mygirl'][1])
            jing.setflag('mygirl')
            jing.addflag('saylove', 2, False)
            db.update(task_id, jing)

            jing_updated = db.getbyid(taskobj.Task, task_id)
            self.assertTrue(jing_updated.name == jing.name)
            self.assertTrue(jing_updated.detail == jing.detail)
            self.assertTrue(jing_updated.due == jing.due)
            self.assertTrue(jing_updated.complete== jing.complete)
            updated_flags = jing_updated.flags
            self.assertTrue(updated_flags['mygirl'][1])
            self.assertTrue(updated_flags.has_key('saylove'))

            # Cannot update tag name with another existing tag in
            # database
            family.name = work.name
            try:
                db.update(tag_id, family)
                self.assertTrue(False)
            except errors.TaskObjectError:
                pass
            # Update tags
            family.name = strutil.u_("Can we be a family?")
            family.weighting = family.weighting * 2
            family.detail = strutil.u_("I still want you")
            db.update(tag_id, family)
            found_tag = db.getbyid(taskobj.Tag, tag_id)

            self.assertTrue(found_tag.name == family.name)
            self.assertTrue(found_tag.detail == family.detail)
            self.assertTrue(found_tag.weighting == family.weighting)
        finally:
            db.close()
    def test_list_obj(self):
        db = sqlite3db.Database(":memory:")
        try:
            jing, family, work = self.create_objs()
            id = db.new(jing)
            flags_before = jing.flags
            tasks = db.list(taskobj.Task)
            self.assertTrue(len(tasks) == 1)
            found_id   = tasks[0][0]
            found_task = tasks[0][1]
            found_weighting = tasks[0][2]
            flags_after = found_task.flags

            # Values should be kept the same
            self.assertTrue(found_id == id)
            self.assertTrue(found_task.name == jing.name)
            self.assertTrue(found_task.due == jing.due)
            self.assertTrue(timeutil.isutctime(found_task.due))
            self.assertTrue(found_task.detail == jing.detail)
            self.assertTrue(found_task.complete is None)
            # flags should be the same
            self.assertTrue(flags_before == flags_after)

            # Tag and task are added seperatedly.
            tag_id = db.new(family)
            found_tags = db.list(taskobj.Tag)
            self.assertTrue(len(found_tags) == 1)

            # Completed object will not be shown
            complete = timeutil.utcdatetime(2010, 7, 10)
            brokeup = taskobj.Task(name = strutil.u_("Broke up"),
                                   detail = strutil.u_("complete"),
                                   due = complete,
                                   complete = complete)
            brokeup_id = db.new(brokeup)
            tasks_ongoing = db.list(taskobj.Task)
            tasks_all = db.list(taskobj.Task, False)
            self.assertTrue(len(tasks_ongoing) + 1 == len(tasks_all))
        finally:
            db.close()

# vim:tw=78:et:sw=4
